﻿using System.Reflection;
using System.Text;
using rpc_service.cache;
using rpc_service.log;
using rpc_service.util;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Primitives;
using rpc_service.config;

namespace rpc_service.core.support.assembly.roslyn;

public class RoslynClassStep : RoslynStep
{
    private RoslynStep[] _methodSteps;
    private RPCMethodLoader _rpcMethodLoader =  new RPCMethodLoader();

    public RoslynClassStep(RoslynStep[] methodSteps)
    {
        _methodSteps = methodSteps;
    }
    
    public StringBuilder process(StringBuilder stringBuilder, Type targetType, MethodInfo method)
    {
        // 配置 using
        stringBuilder = addusing(stringBuilder);
        stringBuilder.AppendLine("namespace DynamicProxy {");
        // 配置 Class 
        stringBuilder.AppendLine($@"class {targetType.Name}Proxy : {targetType.FullName}");
        stringBuilder.AppendLine("{");
        // 生成 logger 
        createLogger(stringBuilder, targetType);
        
        StringBuilder methodStringBuilder = new StringBuilder();
        Dictionary<string, string> dictionary = new Dictionary<string, string>();
        foreach (var targetMethod in targetType.GetMethods())
        {
            if (dictionary.ContainsKey(targetMethod.Name))
            {
                throw new Exception($"Method Name {targetMethod.Name} is must only one");
            }
            
            if (!_rpcMethodLoader.MethodLoader(targetMethod))
            {
                throw new Exception($"Method {targetMethod.Name} is not have RPCMethod");
            }
            
            dictionary.Add(targetMethod.Name, targetMethod.Name);

            foreach (var methodStep in _methodSteps)
            {
                methodStep.process(methodStringBuilder, targetType, targetMethod);
            }
        }
        
        stringBuilder.AppendLine(methodStringBuilder.ToString());
        stringBuilder.AppendLine("}");
        stringBuilder.AppendLine("}");

        if (LoadConfig.Load().IsDebug)
        {
            Console.WriteLine(stringBuilder.ToString());
        }

        return stringBuilder;
    }
    
    private void createLogger(StringBuilder stringBuilder, Type targetType)
    {
        Type iLoggerType = "ILogger".GetTypeByStr();
        Type loggerType = "Logger".GetTypeByStr();
        stringBuilder.AppendLine($@"    private {iLoggerType} _logger = {loggerType}.GetLoggerFactory().CreateLogger(""{targetType.Name}Proxy"");");
    }

    private StringBuilder addusing(StringBuilder stringBuilder)
    {
        stringBuilder.AppendLine($@"using System;");
        stringBuilder.AppendLine($@"using System.Net;");
        stringBuilder.AppendLine($@"using System.Net.Http;");
        stringBuilder.AppendLine($@"using System.Text;");
        stringBuilder.AppendLine($@"using System.Threading.Tasks;");
        stringBuilder.AppendLine($@"using Microsoft.Extensions.Logging;");
        stringBuilder.AppendLine($@"using rpc_service.util;");
        
        return stringBuilder;
    }
}